package model

import (
	"blog2021/tools/logger"
	"time"

	"github.com/jinzhu/gorm"
)

var PostBaseFields = "id, _id, author, title, profile, pv, tags, type, created_at, updated_at"
var PostLessFields = "id, _id, author, title, pv, created_at, updated_at"

type (
	Post struct {
		gorm.Model
		Id      string `gorm:"column:_id"`
		Author  string `gorm:"column:author"`
		Title   string `gorm:"column:title"`
		Profile string `gorm:"column:profile"`
		Content string `gorm:"column:content"`
		Pv      int    `gorm:"column:pv"`
		Tags    string `gorm:"column:tags"`
		Type    int    `gorm:"column:type"`
	}

	PageNumber struct {
		Current int
		Next    int
		List    []int
	}
)

func GetAllPost() []Post {
	var posts []Post
	err := db.Select(PostBaseFields).
		Order("created_at desc").
		Find(&posts).Error
	if err != nil {
		logger.Error(err)
	}
	return posts
}

func GetPostsPage(page int) []Post {
	var posts []Post
	offset := (page - 1) * MaxPageCount
	limit := MaxPageCount
	err := db.Select(PostBaseFields).
		Order("created_at desc").
		Limit(limit).Offset(offset).
		Find(&posts).Error
	if err != nil {
		logger.Error(err)
	}
	return posts
}

func GetPageNumber(page int) PageNumber {
	var pn PageNumber
	var total int
	left := []int{}
	mid := []int{}
	right := []int{}
	pn.Current = page
	if err := db.Model(&Post{}).Count(&total).Error; err != nil {
		return pn
	}

	var maxPage = total / MaxPageCount
	pn.Next = page + 1
	if pn.Next > maxPage {
		pn.Next = 1
	}
	if page < 4 {
		if page < 3 {
			left = []int{1, 2, 3}
		} else if page == 3 {
			left = []int{1, 2, 3, 4}
		}
		right = []int{maxPage}
	} else if page <= maxPage && page >= (maxPage-2) {
		left = []int{1}
		if page == maxPage-2 {
			for i := maxPage - 3; i <= maxPage; i++ {
				right = append(right, i)
			}
		} else {
			for i := maxPage - 2; i <= maxPage; i++ {
				right = append(right, i)
			}
		}
	} else {
		left = []int{1}
		right = []int{maxPage}
		for i := page - 1; i <= page+1; i++ {
			mid = append(mid, i)
		}
	}

	pn.List = left
	pn.List = append(pn.List, -1)
	if len(mid) > 0 {
		pn.List = append(pn.List, mid...)
		pn.List = append(pn.List, -1)
	}
	pn.List = append(pn.List, right...)
	return pn
}

func GetPostPrevNext(post Post) (Post, Post) {
	var prevPost Post
	var nextPost Post
	db.Select(PostLessFields).Where("created_at >= ? and _id != ?", post.CreatedAt, post.Id).Order("created_at asc").Limit(1).Find(&prevPost)
	db.Select(PostLessFields).Where("created_at <= ? and _id != ?", post.CreatedAt, post.Id).Order("created_at desc").Limit(1).Find(&nextPost)
	return prevPost, nextPost
}

func GetPostById(id string) (Post, error) {
	var post Post
	err := db.Where("_id = ?", id).Find(&post).Error
	return post, err
}

func GetLessPostById(id string) (Post, error) {
	var post Post
	err := db.Select(PostLessFields).Where("_id = ?", id).Find(&post).Error
	return post, err
}

func IncrPostById(id string) (Post, error) {
	var post Post
	err := db.Where("_id = ?", id).Find(&post).UpdateColumn("pv", gorm.Expr("pv+?", 1)).Error
	return post, err
}

func GetPostByTag(name string) []Post {
	var posts []Post
	if err := db.Select(PostLessFields).Where("tags like ?", "%"+name+"%").Order("created_at desc").Find(&posts).Error; err != nil {
		logger.Error(err)
	}
	return posts
}

func SearchPost(keyword string, containsContent bool) []Post {
	var posts []Post
	if containsContent {
		if err := db.Select(PostLessFields).Where("title like ? or content like ?", "%"+keyword+"%", "%"+keyword+"%").Order("created_at desc").Find(&posts).Error; err != nil {
			logger.Error(err)
		}
	} else {
		if err := db.Select(PostLessFields).Where("title like ?", "%"+keyword+"%").Order("created_at desc").Find(&posts).Error; err != nil {
			logger.Error(err)
		}
	}

	return posts
}

func GetHotPosts() []Post {
	var posts []Post
	var result []Post
	if err := db.Order("pv desc").Limit(ShowHotCount).Find(&posts).Error; err == nil {
		for _, v := range posts {
			v.Content = ""
			v.Profile = ""
			if v.Title != "我的书签" {
				result = append(result, v)
			}
		}
	}
	return result
}

func GetRecommendPosts() []Post {
	var posts []Post
	from := time.Now()
	to := from.AddDate(0, -3, 0)
	if err := db.Select(PostLessFields).Where("created_at BETWEEN ? AND ?", to, from).Order("pv desc").Limit(ShowHotCount).Find(&posts).Error; err != nil {
		logger.Error("GetRecommendPosts", err)
	}
	return posts
}

func AddPost(post Post) error {
	return db.Create(&post).Error
}

func UpdatePost(post Post) error {
	return db.Save(&post).Error
}

func DeletePostById(pid string) error {
	return db.Where("_id = ?", pid).Delete(Post{}).Error
}

func NextPostId(id string) string {
	var post Post
	if err := db.Select(PostLessFields).Where("_id = ?", id).Find(&post).Error; err == nil {
		var nextPost Post
		if err := db.Select(PostLessFields).Where("id < ?", post.ID).Order("id desc").Limit(1).Find(&nextPost).Error; err == nil {
			return nextPost.Id
		}
	}
	return ""
}
